﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include <GnufIAssetDisplay.h>
#include <GnufNotificationCenterEventArgs.h>

namespace gnuf {
    class GnufProjectDisplay;
    
    class GNUF_EXTENSION_EXPORT GnufAssetDisplay : public IAssetDisplay
    {
        DEFINE_CAST_DERIVED(GnufAssetDisplay, IAssetDisplay)

    protected:
        explicit GnufAssetDisplay();
    public:
        virtual ~GnufAssetDisplay();
        
        bool isHolden() const { return m_holder.IsValid(); }
        
        ///\brief Check a customized asset display.
        ///\return Return it if successful. Return nullptr if failed.
        static GnufAssetDisplay * checkIn(gcmp::OwnerPtr<GnufAssetDisplay> && opCustomized);
        ///\brief Check it out. This object will be deleted.
        void checkOut();

        bool isActive() const { return m_active; }
        
        bool isActivating() const { return m_activating; }
        bool isDeactivating() const { return m_deactivating; }
        bool isClosing() const { return m_closing; }

        virtual void updateCaption(bool wantToNotify) = 0;
        virtual void updateBackground() = 0;
        
        ///\brief Get the size.
        ///\return Return true if successful.
        bool size(int & width, int & height) const;
        ///\brief Resize.
        ///\return Return true if successful.
        bool resize(const int width, const int height);

    protected:
        friend class GnufProjectDisplay;
        void setHolder(GnufProjectDisplay *);
        GnufProjectDisplay * holder()  { return m_holder.Get(); }
        const GnufProjectDisplay * holder() const { return m_holder.Get(); }
        virtual void onPostUnholden() {}
        virtual void onPostHolden() {}

        // Inherits from IAssetDisplay...
        virtual IProjectDisplay * onGetProjectDisplay() override;
        virtual const IProjectDisplay * onGetProjectDisplay() const override;

        virtual void onClose() override;
        virtual void onActivate() override;
        virtual void onDeactivate() override;
        virtual bool onIsActive() const override { return m_active; }
        virtual bool onEqual(const IAssetDisplay *) const;
        virtual void onPreShown() override;
        virtual void onPreHidden() override;
        
        // Give the derived class an opportunity to make a decision 
        // if continue to close.
        virtual bool onDoesContinueToClose()  { return true; }

        // Really do close/activate/deactivate.
        // Return true if activated/deactivated/closed, otherwise return false.
        enum class EResult : std::uint8_t
        {            
            eTrueAndEnded,      // successful and ended, don't have to call endDoing (e.g. endClosing)
            eTrueButNotEnded,   // successful but not ended, have to call endDoing (e.g. endClosing)
            eFalse,             // failed
        };
        virtual GnufAssetDisplay::EResult onDoClose() = 0;
        virtual bool onDoActivate() = 0;
        virtual bool onDoDeactivate() = 0;
        virtual bool onCanDeactivateProgrammatically() const { return true; }
        
        void endCreating();
        void endClosing();
        void endActivating();
        void endDeactivating();
        
        void notify(AssetDisplayEventArgs::EType, bool throughInputChannel = true);
        
    private:
        gcmp::WeakPtr<GnufProjectDisplay> m_holder;
        bool m_active;
        bool m_closing;
        bool m_activating;
        bool m_deactivating;
    };
}
